<template>
	<!-- 日历滚动插件 -->
	<view class="zsy_calendar">
		<!-- 日历顶部信息 -->
		<view class="calendar_info">
			<text class="title">2023年</text>
			<text style="margin-left: 15rpx;margin-right: 15px">|</text>
			<text class="title">{{getWeek()}}</text>
			<text v-show="showBackToTodayBtn()" class="backToToday" :style="{color: dateActiveColor}"
				@tap="goToDate()">回到本周</text>
		</view>
		<!-- 日历轮播 -->
		<view class="calendar_swiper">
			<!-- 收缩情况下的日历轮播 -->
			<swiper key="shrinkSwiper" circular :style="{height: '95rpx'}" :current="current" :duration="duration"
				:skip-hidden-item-layout="true" @change="e => current = e.detail.current">
				<swiper-item v-for="(swiper, swiperIndex) in 3" :key="swiperIndex" class="swiper-item">
					<DateBox :dates="calendarSwiperDates[swiperIndex]" :cellHeight="cellHeight"
						:dateActiveColor="dateActiveColor" @chooseDate="chooseDate" />
				</swiper-item>
			</swiper>
		</view>
		<view style="border-bottom: 1px solid #eee;">

		</view>

	</view>
</template>

<script>
	import {
		parseTime,
		deepClone,
		getLasyDay,
		getLasyDay3
	} from './js/utils.js'
	import DateBox from './monthBox.vue'
	export default {
		name: 'ZsyCalendar',
		components: {
			DateBox
		},
		props: {
			duration: { // 轮播图动画时长
				type: Number,
				default: 300
			},
			cellHeight: { // 一列的高度
				type: Number,
				default: 75
			},
			dateActiveColor: { // 日期选中颜色
				type: String,
				default: '#FE6601'
			},
			sundayIndex: { // 星期天所在索引，0表示第一个、6表示最后一个
				type: Number,
				default: 6
			},
			mode: { // 日历模式
				type: String,
				default: 'open'
			},
			changeSetDefault: { // 月份切换时是否显示一号还是当前月份选中高亮
				type: Boolean,
				default: true
			},
			defaultSelectedDate: { // 默认选中日期
				type: String | null,
				default: null
			},
			date:{
				type: String ,
				default: parseTime(new Date(), '{y}-{m}-{d}')
			}
		},
		data() {
			return {
				today: null, // 今天日期
				selectedDate: null, // 选中日期,
				currDate: null,
				current: 1, // 当前日历轮播默认显示索引
				shrinkCurrent: 1, // 缩放日历轮播默认显示索引
				calendarSwiperDates: [], // 日历轮播日期信息
				dateActive: -1, // 日期选中索引
				swiperByClick: false, // 是否通过点击上月份或下月份的日期进行轮播切换
				shrinkSwiperByClick: false, // 是否通过点击上月份或下月份的日期进行收缩日历的轮播切换
				dateCache: {}, // 日期缓存
				emitTimer: null, // 日期改变向父级传递当前选中日期计时器
				dateClick: false // 是否进行了日期的点击选择
			}
		},
		computed: {
			/* 获取指定日期信息
			isCurDate: 是否获取当天的信息还是选中日期的信息
			index: 0 表示年份 1 表示月份 2 表示日期 */
			getAssignDateInfo() {
				return (isCurDate, index) => {
					return (isCurDate ? this.today : this.currDate).split('-')[index] * 1
				}
			},
			getWeek() {
				return () => {
				
					return this.selectedDate == null ? '' : this.selectedDate[0].month + '.' + this.selectedDate[0]
						.date + '~' + this.selectedDate[6].month + '.' + this.selectedDate[6].date
				}
			},
			showBackToTodayBtn(){
				return ()=>{
				     return false
					
				}
			}

		},
		watch: {
			current(newV, oldV) {
				if (newV === 0 && oldV === 2) { // 右滑
					this.swiperChange(1)
					return
				}
				if (newV === 2 && oldV === 0) { // 左滑
					this.swiperChange(-1)
					return
				}
				if (newV > oldV) { // 右滑
					this.swiperChange(1)
				} else { // 左滑
					this.swiperChange(-1)
				}
			},
			selectedDate: {
				deep: true,
				handler(newV, oldV) {
					if (newV && (oldV === null || this.dateClick)) { // 初始化/日历点击选择时直接返回
						this.emitDate()
						this.dateClick = false
					} else { // 其它情况做防抖处理
						if (this.emitTimer !== null) {
							clearTimeout(this.emitTimer)
						}
						this.emitTimer = setTimeout(() => {
							this.emitDate()
						}, this.duration + 200)
					}
				}
			}
		},
		created() {
			this.init() // 初始化数据
		},
		methods: {
			init() {
				this.today = this.date
				if (this.currDate === null) { // 默认选中日期为当天
					this.currDate = this.today
				}
			
				let year = this.getAssignDateInfo(false, 0)
				let month = this.getAssignDateInfo(false, 1)
				//
				const normalWeek = ['日', '一', '二', '三', '四', '五', '六'] // 正常周数
				const monthlastDay = getLasyDay(year, month)
				const monthlastDayName = normalWeek[monthlastDay] // 获取本月一号为星期几
				const monthlastDayIndex = normalWeek.indexOf(monthlastDayName) // 计算本月一号在日历周数中的
				if (monthlastDayIndex !== 0 && (eval(getLasyDay3(year,month)) - eval(this.getAssignDateInfo(true, 2)) <
						monthlastDayIndex)) {
							
					this.today = parseTime(new Date(month === 12 ? year + 1 : year, month === 12 ? 1 : month + 1, 0),
						'{y}-{m}') + '-01'
					year = this.getAssignDateInfo(true, 0)
					month = this.getAssignDateInfo(true, 1)
					this.currDate = this.today

				}
				const cur = this.generateCalendar(year, month)
				const prev = this.generateCalendar(month === 1 ? year - 1 : year, month === 1 ? 12 : month - 1)
				const next = this.generateCalendar(month === 12 ? year + 1 : year, month === 12 ? 1 : month + 1)
				if (this.current === 0) {
					this.calendarSwiperDates = [cur, next, prev]
				} else if (this.current === 1) {
					this.calendarSwiperDates = [prev, cur, next]
				} else if (this.current === 2) {
					this.calendarSwiperDates = [next, prev, cur]
				}
			},
			//按月生成数据
			generateCalendar(year, month) {
		
				let calendarDate = []
				let dateArray = []
			
				//读缓存
				if (this.dateCache[`${year}-${month}`]) {
					dateArray = deepClone(this.dateCache[`${year}-${month}`])
				} else {
					const monthDates = new Date(year, month, 0).getDate() // 获取此月份总天数
					const normalWeek = ['一', '二', '三', '四', '五', '六', '日'] // 正常周数
					const monthFirstDay = normalWeek[new Date(year, month - 1, 0).getDay()] // 获取本月一号为星期几
					const monthFirstDayIndex = normalWeek.indexOf(monthFirstDay) // 计算本月一号在日历周数中的索引，索引之前的填充上个月的后几天
					// 本月一号在日历中不是第一个位置，需要进行填充
					if (monthFirstDayIndex !== 0) {
						const prevMonthDates = new Date(year, month - 1, 0).getDate() // 获取上一个月份的总天数
						// 填充本月一号之前的数据
						for (let i = 0; i < monthFirstDayIndex; i++) {
							const item = {
								year: month === 1 ? year - 1 : year,
								month: month === 1 ? 12 : month - 1,
								date: prevMonthDates - i,
								type: 'prev'
							}
							// 判断填充的日期是否包含今天日期
							this.theDateIsToday(item)
							calendarDate.unshift(item)
						}
					}
					// 循环生成当月所有日期
					for (let i = 1; i <= monthDates; i++) {
						const item = {
							year,
							month,
							date: i,
							isSelected: false,
							isToday: false,
							type: 'cur'
						}
						// 今天的日期在不在里面
						this.theDateIsToday(item)
						calendarDate.push(item)
					}
					// 进行日期的默认选中
				    let bb = false
					if (year === this.getAssignDateInfo(false, 0) && month === this.getAssignDateInfo(false, 1)) {
						for (let i = 0, len = calendarDate.length; i < len; i++) {
							if (calendarDate[i].date === this.getAssignDateInfo(false, 2)) {
								bb = true;
								calendarDate[i].isSelected = true
								break
							}
						}
					}
					if(!bb){
						calendarDate[0].isSelected = true
					}
				
					const residue = calendarDate.length % 7
					dateArray.push(calendarDate.splice(0, 7))
					dateArray.push(calendarDate.splice(0, 7))
					dateArray.push(calendarDate.splice(0, 7))
					dateArray.push(calendarDate.splice(0, 7))
					// 判断是否需要填充下个月的前几天
					if (residue !== 0) {
						for (let i = 1; i <= 7 - residue; i++) {
							const item = {
								year: month === 12 ? year + 1 : year,
								month: month === 12 ? 1 : month + 1,
								date: i,
								type: 'next'
							}
							// 下个月的前几天包含今天
							this.theDateIsToday(item)
							calendarDate.push(item)
						}
					} else {
						dateArray.push(calendarDate.splice(0, 7))
					}

					this.dateCache[`${year}-${month}`] = deepClone(dateArray)
				}



                
				//
				let selectArray = dateArray.find(item => item.findIndex(k => k.isSelected) > -1)
				if ((year === this.getAssignDateInfo(false, 0) && month === this.getAssignDateInfo(false, 1)) && selectArray != undefined) {
					this.selectedDate = selectArray
					this.dateActive = dateArray.findIndex(item => item.findIndex(k => k.isSelected) > -1)
				}

         

				return dateArray

			},
			theDateIsToday(item) {

				if (item.year + '-' + item.month + '-' + item.date === this.getAssignDateInfo(true, 0) + '-' + this
					.getAssignDateInfo(true, 1) + '-' + this.getAssignDateInfo(true, 2)) {
					item.isToday = true
				}
			},
			//滑动切换
			swiperChange(type) {
				
				this.getPrevOrNextDate(type)
				setTimeout(() => { // 设置定时器是为了防止轮播切换时生成数据造成页面卡顿
					this.init() // 初始化日历轮播日期信息
				},  this.duration )
			},
			getPrevOrNextDate(type) {
				
				const year = this.getAssignDateInfo(false, 0)
				let month = this.getAssignDateInfo(false, 1)
			
				month = month + type
				// 判断切换月份时选中当前日期高亮还是一号，若选中当前日期高亮需进行大小判断
				this.today =  parseTime(new Date(year, month - 1, 1), '{y}-{m}-{d}')
				this.currDate = this.today
				
			},
			// 日历轮播展开的情况下选择日期
			chooseDate(dateInfo, dateIndex) {
				// 重复点击后续不做处理
				if (dateInfo.findIndex(item => item.isSelected) > -1) return false

				this.selectedDate = dateInfo
				// 将当前选中的日期清空并选中最新的日期
				this.calendarSwiperDates[this.current][this.dateActive].map(item => {
					item.isSelected = false
					return item
				})

				this.dateActive = dateIndex
				this.calendarSwiperDates[this.current][this.dateActive][0].isSelected = true
				
				this.dateClick = true

			},
			goToDate(){
				
			},
			emitDate() {
				const dateArray = this.calendarSwiperDates[this.current][this.dateActive]
				const e = {
					selectedDate: dateArray,
					type:'week'
					
				}
				this.$emit('change', e)
			
			}


		}
	}
</script>

<style scoped>
	.zsy_calendar {
		width: 100%;
		padding: 20rpx 0;
		box-sizing: border-box;
		background-color: #fff;
		border-radius: 20rpx;
	}

	/* 日历顶部信息 */
	.calendar_info {
		display: flex;
		align-items: center;
		padding: 0 20rpx;
	}

	.calendar_info .title {
		font-size: 34rpx;
		font-weight: bold;
		color: #2C2C2C;
	}

	.calendar_info .desc {
		margin-left: 29rpx;
		font-size: 28rpx;
		color: #959595;
	}

	.calendar_info .backToToday {
		margin-left: auto;
		font-size: 24rpx;
	}

	/* 日历顶部信息 */

	/* 日历周数 */
	.calendar_week {
		display: flex;
		align-items: center;
		justify-content: space-between;
		font-size: 26rpx;
		color: #959595;
		margin: 20rpx 0rpx;
	}

	.calendar_week .calendar_week__item {
		width: calc(100% / 7);
		text-align: center;
	}

	/* 日历周数 */

	/* 日历切换模式 */
	.calendar_toggle {
		position: relative;
		padding: 10rpx 0;
		margin: 10rpx 20rpx 0;
		display: flex;
		justify-content: center;
	}

	.calendar_toggle .icon {
		width: 30rpx;
		height: 30rpx;
		background-image: url('../../static/zsy-calendar/arrow.png');
		background-size: contain;
		background-repeat: no-repeat;
		margin: 0 auto;
		transition: all .3s;
	}

	.icon.down {
		transform: rotate(180deg);
	}

	.calendar_toggle::before,
	.calendar_toggle::after {
		width: calc(50% - 30rpx);
		border-top: solid 2rpx #EAEAEA;
		content: '';
		display: block;
		position: absolute;
		top: 50%;
		transform: translateY(-50%);
	}

	.calendar_toggle::before {
		left: 0;
	}

	.calendar_toggle::after {
		right: 0;
	}

	/* 日历切换模式 */
</style>
